package main

/* 
  by zy,
  上传 SSL 证书

  -upload -cert <cert file> -key <key file> -name <name> -cn <common name> [-deploy -fqdn <domain>]
 
*/

import ( 
  "os"
  "fmt"
  "net/http"
  "encoding/json"
)

type ReqBodyUpload struct { // POST /sslcert, Content-Type: application/json
  CertName        string `json:"name"`
  CommonName      string `json:"common_name"`
  KeyStr          string `json:"pri"`
  CertStr         string `json:"ca"`
}

/*
响应体
  //StatusCode: 200
{
  "code": 200,
  "error": "",
  "certID": "690870280e5e768c40e288b3"
}

  //StatusCode: 401
{
  "error": "bad token",
  "error_code": "BadToken"
}
*/
type RespBodyUpload struct {
  Code         int    `json:"code"`
  Error        string `json:"error"`
  ErrorCode    string `json:"error_code"`
  CertID       string `json:"certID"`
}

// 上传
func handleUpload(cfg *CLI) {
  var err error
  // 加载证书和密钥
  if err := loadCertAndKey(cfg); err != nil {
    fmt.Fprintln(os.Stderr, err)
    os.Exit(ExitFileError)
  }

  // 构造 Request Body
  jsonData, err := makeUploadJSON(cfg)
  if err != nil {
    fmt.Fprintf(os.Stderr, "failed to marshal JSON: %v\n", err)
    os.Exit(ExitMarshalError)
  }

  // 发送请求
  resp, err := sendUploadRequest(cfg, jsonData)
  if err != nil {
    fmt.Fprintf(os.Stderr, "failed to upload: %v\n", err)
    os.Exit(ExitRequestError)
  }
  defer resp.Body.Close()

  fmt.Printf("StatusCode: %d\n", resp.StatusCode);

  r, err := parseResp[RespBodyUpload](resp)
  if err != nil {
    fmt.Fprintf(os.Stderr, "failed to parse response: %v\n", err)
    os.Exit(ExitUnmarshalError)
  }
  if resp.StatusCode == 200 {
    cfg.CertID = r.CertID
    fmt.Printf("StatusCode: %d\nCertID: %s\n", r.Code, r.CertID)
    if cfg.Deploy {
      handleSet(cfg)
    }
  } else {
    fmt.Printf("StatusCode: %d\nError: %s\nErrorCode: %s\n", resp.StatusCode, r.Error, r.ErrorCode)
  }
}

func makeUploadJSON(cfg *CLI) ([]byte, error) {
  reqBody := ReqBodyUpload{
    CertName:   cfg.CertName,
    CommonName: cfg.CN,
    KeyStr:     cfg.KeyStr,
    CertStr:    cfg.CertStr,
  }
  return json.Marshal(&reqBody)
}

func sendUploadRequest(cfg *CLI, body []byte) (*http.Response, error) { // POST /sslcert, Content-Type: application/json
  return sendQiNiuRequest(cfg, http.MethodPost, "/sslcert", "", body)
}

